module mod_chem_unit

   use iso_fortran_env, only: dp => real64
   type :: type_chem_unit
      character(len=:), allocatable :: length
      character(len=:), allocatable :: time
      character(len=:), allocatable :: quantity
      character(len=:), allocatable :: activation_energy
      character(len=:), allocatable :: temperature
      character(len=:), allocatable :: mass
      character(len=:), allocatable :: current
      character(len=:), allocatable :: pressure
      character(len=:), allocatable :: energy
   end type type_chem_unit

contains

   function get_factor_trans_units(unit1, unit2, type) result(factor)
      implicit none
      character(len=*), intent(in) :: unit1, unit2
      character(len=*), intent(in) :: type
      real(dp) :: factor

      select case (trim(type))
      case ("quantity")
         factor = get_factor_trans_units_quantity(unit1, unit2)
      case ("length")
         factor = get_factor_trans_units_length(unit1, unit2)
      case ("time")
         factor = get_factor_trans_units_time(unit1, unit2)
      case ("temperature")
         factor = 1.0_dp
      case ("mass")
         factor = 1.0_dp
      case ("energy")
         factor = get_factor_trans_units_energy(unit1, unit2)
      case default
         print *, "unkown type ", type
         error stop
      end select

   end function get_factor_trans_units

   function get_factor_trans_units_quantity(unit1, unit2) result(factor)
      implicit none
      character(len=*), intent(in) :: unit1, unit2
      real(dp) :: factor

      if (trim(unit1) == "mol" .and. trim(unit2) == "kmol") then
         factor = 1.0_dp/1000.0_dp
      elseif (trim(unit1) == "kmol" .and. trim(unit2) == "mol") then
         factor = 1000.0_dp
      elseif (trim(unit1) == "mol" .and. trim(unit2) == "mol") then
         factor = 1.0_dp
      elseif (trim(unit1) == "kmol" .and. trim(unit2) == "kmol") then
         factor = 1.0_dp
      else
         print *, "unkown units for quantity ", unit1, " and ", unit2
         error stop
      end if

   end function get_factor_trans_units_quantity

   function get_factor_trans_units_length(unit1, unit2) result(factor)
      implicit none
      character(len=*), intent(in) :: unit1, unit2
      real(dp) :: factor

      if (trim(unit1) == "m" .and. trim(unit2) == "cm") then
         factor = 100.0_dp
      elseif (trim(unit1) == "cm" .and. trim(unit2) == "m") then
         factor = 1.0_dp/100.0_dp
      elseif (trim(unit1) == "m" .and. trim(unit2) == "m") then
         factor = 1.0_dp
      elseif (trim(unit1) == "cm" .and. trim(unit2) == "cm") then
         factor = 1.0_dp
      else
         print *, "unkown units for length ", unit1, " and ", unit2
         error stop
      end if

   end function get_factor_trans_units_length

   function get_factor_trans_units_time(unit1, unit2) result(factor)
      implicit none
      character(len=*), intent(in) :: unit1, unit2
      real(dp) :: factor

      if (trim(unit1) == "s" .and. trim(unit2) == "min") then
         factor = 1.0_dp/60.0_dp
      elseif (trim(unit1) == "min" .and. trim(unit2) == "s") then
         factor = 60.0_dp
      elseif (trim(unit1) == "s" .and. trim(unit2) == "s") then
         factor = 1.0_dp
      elseif (trim(unit1) == "min" .and. trim(unit2) == "min") then
         factor = 1.0_dp
      else
         print *, "unkown units for time ", unit1, " and ", unit2
         error stop
      end if

   end function get_factor_trans_units_time

   function get_factor_trans_units_energy(unit1, unit2) result(factor)
      implicit none
      character(len=*), intent(in) :: unit1, unit2
      real(dp) :: factor

      if (trim(unit1) == "J" .and. trim(unit2) == "kJ") then
         factor = 1.0_dp/1000.0_dp
      elseif (trim(unit1) == "kJ" .and. trim(unit2) == "J") then
         factor = 1000.0_dp
      elseif (trim(unit1) == "cal" .and. trim(unit2) == "J") then
         factor = 4.184_dp
      elseif (trim(unit1) == "J" .and. trim(unit2) == "J") then
         factor = 1.0_dp
      elseif (trim(unit1) == "kJ" .and. trim(unit2) == "kJ") then
         factor = 1.0_dp
      else
         print *, "unkown units for energy ", unit1, " and ", unit2
         error stop
      end if

   end function get_factor_trans_units_energy

end module mod_chem_unit
